﻿using System.Collections.Generic;
using System.IO;
using UnityEngine;
using System;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace QFramework
{
    [CreateAssetMenu(menuName = "@ItemKit/Create Item Database")]
    public class ItemDatabase : ScriptableObject
    {
        [DisplayLabel("命名空间")]
        public string Namespace = "QFramework.Example";
        public List<Item> Items;
    }

#if UNITY_EDITOR
    [CustomEditor(typeof(ItemDatabase))]
    public class ItemDatabaseEditor : Editor
    {
        public class ItemEditorObj
        {
            public bool Foldout
            {
                get => EditorPrefs.GetBool($"{Item.GetKey}_foldout", true);
                set => EditorPrefs.SetBool($"{Item.GetKey}_foldout", value);
            }
            public Editor Editor = null;
            public Item Item = null;
        }

        private SerializedProperty mItems;
        private readonly List<ItemEditorObj> mItemEditorObjs = new();
        private readonly FluentGUIStyle mHeader = FluentGUIStyle.Label().FontBold();
        private readonly Queue<Action> mActionQueue = new();
        private string mSearchKey = "";

        private void OnEnable()
        {
            mItems = serializedObject.FindProperty("Items");

            RefreshItemEditors();
        }

        public override void OnInspectorGUI()
        {
            if (mItems.arraySize != mItemEditorObjs.Count)
            {
                RefreshItemEditors();
            }

            GUILayout.BeginVertical("box");
            serializedObject.Update();
            serializedObject.DrawProperties(false, 0);
            if (GUILayout.Button("生成代码"))
            {
                var itemDb = target as ItemDatabase;

                var filePath = AssetDatabase.GetAssetPath(target).GetFolderPath() + "/Items.cs";

                var rootCode = new RootCode()
                    .Using("UnityEngine")
                    .Using("QFramework")
                    .EmptyLine()
                    .Namespace(itemDb.Namespace, ns =>
                    {
                        ns.Class("Items", string.Empty, false, false, c =>
                        {
                            foreach (var item in itemDb.Items)
                            {
                                c.Custom($"public static IItem {item.Key} => ItemKit.DictItem[\"{item.Key}\"];");
                                c.Custom($"public static string {item.Key}_key = \"{item.Key}\";");
                            }
                        });
                    });

                using var fileWriter = File.CreateText(filePath);
                var codeWriter = new FileCodeWriter(fileWriter);
                rootCode.Gen(codeWriter);

                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
            GUILayout.EndVertical();

            EditorGUILayout.Separator();
            GUILayout.Label("物品列表:", mHeader);
            GUILayout.BeginHorizontal();
            GUILayout.Label("搜索:", GUILayout.Width(40));
            mSearchKey = EditorGUILayout.TextField(mSearchKey);
            GUILayout.EndHorizontal();

            for (int i = 0; i < mItemEditorObjs.Count; i++)
            {
                var itemEditor = mItemEditorObjs[i];

                if (!itemEditor.Item.GetName.Contains(mSearchKey) && !itemEditor.Item.GetKey.Contains(mSearchKey)) continue;

                GUILayout.BeginVertical("box");
                GUILayout.BeginHorizontal();
                itemEditor.Foldout = EditorGUILayout.Foldout(itemEditor.Foldout, itemEditor.Item.GetName);
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("-"))
                {
                    var index = i;
                    if (EditorUtility.DisplayDialog("Delete Item", "Do you want to delete this item?", "Yes,Delete", "No,Cancel"))
                    {
                        mActionQueue.Enqueue(() =>
                        {
                            var arraryElemnt = mItems.GetArrayElementAtIndex(index);
                            AssetDatabase.RemoveObjectFromAsset(arraryElemnt.objectReferenceValue);
                            mItems.DeleteArrayElementAtIndex(index);

                            serializedObject.ApplyModifiedPropertiesWithoutUndo();
                            AssetDatabase.SaveAssets();
                            AssetDatabase.Refresh();
                        });
                    }
                }
                GUILayout.EndHorizontal();
                if (itemEditor.Foldout)
                {
                    itemEditor.Editor.OnInspectorGUI();
                }
                GUILayout.EndVertical();
            }

            if (GUILayout.Button("创建物品"))
            {
                mActionQueue.Enqueue(() =>
                {
                    var item = CreateInstance<Item>();
                    item.name = nameof(Item);
                    item.Name = "新物品";
                    item.Key = "item_key";
                    AssetDatabase.AddObjectToAsset(item, target);
                    mItems.InsertArrayElementAtIndex(mItems.arraySize);

                    var arraryElemnt = mItems.GetArrayElementAtIndex(mItems.arraySize - 1);
                    arraryElemnt.objectReferenceValue = item;

                    serializedObject.ApplyModifiedPropertiesWithoutUndo();
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                });
            }

            if (mActionQueue.Count > 0)
            {
                mActionQueue.Dequeue().Invoke();
            }

            serializedObject.ApplyModifiedProperties();
        }

        private void RefreshItemEditors()
        {
            mItemEditorObjs.Clear();

            for (int i = 0; i < mItems.arraySize; i++)
            {
                var itemSo = mItems.GetArrayElementAtIndex(i);
                var editor = CreateEditor(itemSo.objectReferenceValue);

                mItemEditorObjs.Add(new ItemEditorObj()
                {
                    Editor = editor,
                    Item = itemSo.objectReferenceValue as Item,
                });
            }
        }

    }
#endif
}
